////////////////////////////////////////////////////////////////////////////////
/// @file    play_wavfile.c
/// @author  AE TEAM
/// @brief   THIS FILE PROVIDES ALL THE SYSTEM FUNCTIONS.
////////////////////////////////////////////////////////////////////////////////
/// @attention
///
/// THE EXISTING FIRMWARE IS ONLY FOR REFERENCE, WHICH IS DESIGNED TO PROVIDE
/// CUSTOMERS WITH CODING INFORMATION ABOUT THEIR PRODUCTS SO THEY CAN SAVE
/// TIME. THEREFORE, MINDMOTION SHALL NOT BE LIABLE FOR ANY DIRECT, INDIRECT OR
/// CONSEQUENTIAL DAMAGES ABOUT ANY CLAIMS ARISING OUT OF THE CONTENT OF SUCH
/// HARDWARE AND/OR THE USE OF THE CODING INFORMATION CONTAINED HEREIN IN
/// CONNECTION WITH PRODUCTS MADE BY CUSTOMERS.
///
/// <H2><CENTER>&COPY; COPYRIGHT MINDMOTION </CENTER></H2>
////////////////////////////////////////////////////////////////////////////////
// Define to prevent recursive inclusion
#define _PLAY_WAVFILE_C_

// Files includes

//file play_wavfile.c
#include "HAL_conf.h"
#include "HAL_device.h"
#include <stdio.h>
#include <string.h>
//#include "bsp_WM8978.h"

#include "play_wavfile.h"
#include "sdio.h"
#include "ff.h"
#include "fatfs.h"
#include "sdio_sdcard.h"

#include "uart.h"
#include "delay.h"

#include "mp3dec.h"
#include "mp3common.h"

#include "string.h"


#include "i2s_config.h"
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup MM32_Example_Layer
/// @{

////////////////////////////////////////////////////////////////////////////////
/// @addtogroup PLAY_WAVFILE
/// @{

////////////////////////////////////////////////////////////////////////////////
/// @addtogroup PLAY_WAVFILE_Exported_Constants
/// @{

#define READBUF_SIZE 4096
#define BUFF_SIZE 2304
HMP3Decoder hMP3Decoder;
MP3FrameInfo mp3FrameInfo;
int bytesLeft;

u8  readBuf[READBUF_SIZE];
u8* readPtr;
int offset;
static  short buffer3[BUFF_SIZE] = {0x00};
static  short buffer4[BUFF_SIZE] = {0x00};
short*   Decbuf;

SPI_I2S_AUDIO_FREQ_TypeDef  samprate;

static uint8_t buffer_switch = 1;


////////////////////////////////////////////////////////////////////////////////
/// @brief  Transfer files.
/// @param  None.
/// @retval  0.
////////////////////////////////////////////////////////////////////////////////
static void I2S_TX_DMA_Init(u8* buf0, u16 num)
{

    DMA_InitTypeDef  DMA_InitStructure;
    RCC_AHBPeriphClockCmd(RCC_AHBENR_DMA2, ENABLE);
    DMA_DeInit(DMA2_Channel2);

    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32) & (SPI3->TXREG);
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)buf0;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
    DMA_InitStructure.DMA_BufferSize = num;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    DMA_InitStructure.DMA_Auto_reload = DMA_Auto_Reload_Enable;
    DMA_Init(DMA2_Channel2, &DMA_InitStructure);
}
void Audio_MAL_Play(uint32_t Addr, uint32_t Size)
{
    DMA_Channel_TypeDef* ch;
    ch = DMA2_Channel2;
    CLEAR_BIT(SPI3->GCR, SPI_GCR_SPIEN);
    MODIFY_REG(ch->CCR, DMA_CCR_EN, DISABLE << DMA_CCR_EN_Pos);
    ch->CMAR = Addr;
    ch->CNDTR = Size;
    SET_BIT(SPI3->GCR, SPI_GCR_SPIEN);
    MODIFY_REG(ch->CCR, DMA_CCR_EN, ENABLE << DMA_CCR_EN_Pos);
}
static FIL fsrc;      // file objects

void PlayMP3File(void)
{
    DIR dirs;
    FILINFO finfo;
    FRESULT res;
    static UINT br;

    DELAY_Init();
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOC | RCC_AHBPeriph_GPIOD | RCC_AHBPeriph_GPIOE, ENABLE);
    RCC_AHBPeriphClockCmd(RCC_AHBENR_SDIO, ENABLE);
    CONSOLE_Init(115200);

    SDIO_ConfigInit();
    printf("SDCARD TEST\r\n");
    while(SD_Init()) {
        printf("SD Card Error!\r\n");
    }
    MX_FATFS_Init();
    f_mount(&SDFatFS, (TCHAR const*)SDPath, 0);

    u8 buff[2] = {0x01, 0x02};
    I2S_TX_DMA_Init(&buff[0], 1);
    DMA_Cmd(DMA2_Channel2, ENABLE);

//  while(1){
    if (f_opendir(&dirs, "") == FR_OK) {              //success to open directory
        while (f_readdir(&dirs, &finfo) == FR_OK) {       //if there is file in this directory
            if (finfo.fattrib & AM_ARC) {
                if(!finfo.fname[0])
                    break;
                printf("\r\n Now Playing:[");
                printf(finfo.fname);
                printf("]\r\n");
                res = f_open(&fsrc, finfo.fname, FA_OPEN_EXISTING | FA_READ);
                SET_BIT(SPI3->GCR, SPI_GCR_SPIEN);
                MODIFY_REG(DMA2_Channel2->CCR, DMA_CCR_EN, ENABLE << DMA_CCR_EN_Pos);

                hMP3Decoder = MP3InitDecoder();

                readPtr = readBuf;
                res = f_read(&fsrc, readBuf, READBUF_SIZE, &br);
                bytesLeft += br;

                buffer_switch = 0;
                while(1) {
                    offset = MP3FindSyncWord(readPtr, bytesLeft); //assume EOF if no sync found
                    if(offset < 0)break;
                    readPtr += offset; //data start point
                    bytesLeft -= offset; //in buffer
                    if(bytesLeft < READBUF_SIZE) {
                        memmove(readBuf, readPtr, bytesLeft);
                        res = f_read(&fsrc, readBuf + bytesLeft, READBUF_SIZE - bytesLeft, &br);
                        if((res) || (br == 0)) break;
                        if(br < READBUF_SIZE - bytesLeft)
                            memset(readBuf + bytesLeft + br, 0, READBUF_SIZE - bytesLeft - br);
                        bytesLeft = READBUF_SIZE;
                        readPtr = readBuf;
                    }
                    MP3GetLastFrameInfo(hMP3Decoder, &mp3FrameInfo);

                    if((samprate != mp3FrameInfo.samprate) && (mp3FrameInfo.samprate != 0)) {
//                                               wm8978_CfgAudioIF(I2S_Standard_Phillips, mp3FrameInfo.bitsPerSample, SPI_Mode_Master);
                        //   I2S_StartPlay((SPI_I2S_STANDARD_TypeDef)I2S_Standard_Phillips, (SPI_I2S_DATAFORMAT_TypeDef)mp3FrameInfo.bitsPerSample, (SPI_I2S_AUDIO_FREQ_TypeDef)mp3FrameInfo.samprate);
                        samprate = (SPI_I2S_AUDIO_FREQ_TypeDef) mp3FrameInfo.samprate;
                    }
                    while(1) {
                        if(DMA_GetITStatus(DMA2_IT_TC2) == SET) {
                            DMA_ClearITPendingBit(DMA2_IT_TC2);

                            if(buffer_switch == 0) {
                                Audio_MAL_Play((u32)buffer4, BUFF_SIZE);
                                MP3Decode(hMP3Decoder, &readPtr, &bytesLeft, buffer3, 0);
                                buffer_switch = 1;
                                break;
                            }
                            else {
                                Audio_MAL_Play((u32)buffer3, BUFF_SIZE);
                                MP3Decode(hMP3Decoder, &readPtr, &bytesLeft, buffer4, 0);
                                buffer_switch = 0;
                                break;
                            }
                        }
                    }

                }
                CLEAR_BIT(SPI3->GCR, SPI_GCR_SPIEN);
                MODIFY_REG(DMA2_Channel2->CCR, DMA_CCR_EN, DISABLE << DMA_CCR_EN_Pos);
                f_close(&fsrc);
                bytesLeft = 0;
            }
        }
    }
    while(1);
//   }


}
//////////////////////////////////////////////////////////////////////////////////
///// @brief  I2S initialize.
///// @param  None.
///// @retval  0.
//////////////////////////////////////////////////////////////////////////////////
//void initI2S_CodecMode1(void)
//{
//    DELAY_Init();
//    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOC | RCC_AHBPeriph_GPIOD | RCC_AHBPeriph_GPIOE, ENABLE);
//    RCC_AHBPeriphClockCmd(RCC_AHBENR_SDIO, ENABLE);
//    CONSOLE_Init(115200);

//    wm8978_Init();

//    I2S_CODEC_Init();

//    StartPlay();

//}

//////////////////////////////////////////////////////////////////////////////////
///// @brief  I2S with WM8978 and MM32 starts to play.
///// @param  None
///// @retval None
//////////////////////////////////////////////////////////////////////////////////
//void StartPlay(void)
//{
//    int i;

//    i = 100000;
//    while(i--);
//    wm8978_Init();
//    I2S_Stop();
//
//    wm8978_Dac2Spk();
//
//    wm8978_ChangeVolume(10, 10);
//
//    wm8978_CfgAudioIF(I2S_Standard_Phillips, 16, SPI_Mode_Master);
//
//    I2S_StartPlay((SPI_I2S_STANDARD_TypeDef)I2S_Standard_Phillips, (SPI_I2S_DATAFORMAT_TypeDef)I2S_DataFormat_16b, I2S_AudioFreq_44k);
//    samprate = I2S_AudioFreq_44k;
//}

////////////////////////////////////////////////////////////////////////////////
/// @brief  play music.
/// @param  None.
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
void PlayMP3FileDemo(void)
{
    //  initI2S_CodecMode1();
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOC | RCC_AHBPeriph_GPIOD | RCC_AHBPeriph_GPIOE, ENABLE);
    RCC_AHBPeriphClockCmd(RCC_AHBENR_SDIO, ENABLE);

    I2S_CODEC_Init();

    StartPlay();
    I2S_PWR_ON();

    while(1) {
        PlayMP3File();
    }
}

/// @}

/// @}

/// @}

